<template>
  <div ref="block" class="column block no-wrap">
    <div class="upper"></div>
    <div
      :class="`lower ${selected ? 'selected' : ''}`"
      @mousedown="startDrag($event, 'middle')"
    >
      <div
        class="content one-line-text non-selectable"
        @dblclick="showPopupEditor = true"
      >
        {{ text }}
        <q-popup-proxy v-model="showPopupEditor" no-parent-event>
          <q-input
            filled
            dense
            v-model="_text"
            @keyup.enter="showPopupEditor = false"
          ></q-input>
        </q-popup-proxy>
      </div>
      <q-menu touch-position context-menu auto-close>
        <q-list dense>
          <q-item clickable @click="onDelete">
            <q-item-section>Delete</q-item-section>
          </q-item>
        </q-list>
      </q-menu>
    </div>
    <div class="handle left" @mousedown="startDrag($event, 'left')"></div>
    <div class="handle right" @mousedown="startDrag($event, 'right')"></div>
  </div>
</template>
<script setup lang="ts">
import { ref, watch, computed, onMounted } from 'vue';
const props = defineProps({
  scale: {
    type: Number,
    default: 0,
  },
  zoom: {
    type: Number,
    default: 1,
  },
  startTime: {
    type: Number,
    default: 0,
  },
  endTime: {
    type: Number,
    default: 0,
  },
  duration: {
    type: Number,
    default: 0,
  },
  text: {
    type: String,
    default: '',
  },
});
const emit = defineEmits([
  'update:duration',
  'update:start',
  'update:text',
  'delete',
]);
const start = ref(props.startTime);
const isDragging = ref(false);
const showPopupEditor = ref(false);
const selected = ref(false);
function select() {
  selected.value = true;
}
function unselect() {
  selected.value = false;
}
const _duration = computed({
  get() {
    return props.endTime - props.startTime;
  },
  set(value) {
    emit('update:duration', value);
  },
});
const _start = computed({
  get() {
    return props.startTime;
  },
  set(value) {
    emit('update:start', value);
  },
});
const _text = computed<string>({
  get() {
    return props.text;
  },
  set(value) {
    emit('update:text', value);
  },
});
const width = ref(0);
const block = ref<HTMLDivElement>();
watch(
  () => props.startTime,
  () => {
    refresh();
  }
);
watch(
  () => props.scale,
  () => {
    refresh();
  }
);
watch(
  () => props.zoom,
  () => {
    refresh();
  }
);
watch(
  () => props.duration,
  () => {
    refresh();
  }
);

function refresh() {
  const x = props.scale * props.startTime * props.zoom;
  width.value = props.scale * props.duration * props.zoom;
  if (block.value) {
    block.value!.style.left = `${x}px`;
    block.value!.style.width = `${width.value}px`;
  }
}
onMounted(() => {
  refresh();
});

let pos = { x: 0, left: 0, width: 0 };
let side = '';
let oldStart = 0;
function startDrag(event: MouseEvent, dir: string) {
  event.stopPropagation();
  event.preventDefault();
  isDragging.value = true;
  window.addEventListener('mouseup', onMouseUp);
  window.addEventListener('mousemove', onMouseMove);
  side = dir;
  pos.x = event.clientX;
  if (side === 'left') {
    // slice left
    pos.left = parseInt(block.value!.style.left) | 0;
    pos.width = block.value!.clientWidth;
    oldStart = start.value;
  } else if (side === 'right') {
    // slice right
    pos.width = block.value!.clientWidth;
  } else {
    // change position
    pos.left = parseInt(block.value!.style.left) | 0;
  }
}
function onMouseUp(event: MouseEvent) {
  event.stopPropagation();
  event.preventDefault();
  isDragging.value = false;
  window.removeEventListener('mouseup', onMouseUp);
  window.removeEventListener('mousemove', onMouseMove);
}
function onMouseMove(event: MouseEvent) {
  event.stopPropagation();
  event.preventDefault();
  if (side === 'left') {
    pos.left += event.movementX;
    pos.width -= event.movementX;
    _start.value = px2time(pos.left);
    _duration.value = px2time(pos.width);
  } else if (side === 'right') {
    pos.width += event.movementX;
    _duration.value = px2time(pos.width);
  } else {
    pos.left += event.movementX;
    _start.value = px2time(pos.left);
  }
}
function px2time(px: number) {
  return px / (props.scale * props.zoom);
}
function onDelete() {
  emit('delete');
}
defineExpose({
  select,
  unselect,
});
</script>
<style lang="sass" scoped>

$border-color: #00B5BC
.selected
  border: 1px solid white !important
.block
  position: absolute
  .upper
    height: 21px
  .lower
    border: 1px solid $border-color
    background-color: rgba(0,181,188,0.6)
    height: 34px
    cursor: grab
    .content
      padding-left: 5px
      line-height: 34px
      max-width: calc(100% - 10px)
  .handle
    width: 5px
    height: 20px
    background-color: $border-color
    position: absolute
  .left
    left: 0px
    top: 28px
    cursor: e-resize
  .right
    right: 0px
    top: 28px
    cursor: e-resize
</style>
